#if UNITY_EDITOR
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using Batch2D;
using CSUtils;
using Spine2;
using U3dUtils;
using U3dUtilsEditor;
using UnityEditor;
using UnityEngine;

public class Editor_SpineUtils {
    const string _tag = "Editor_SpineUtils";

    [MenuItem("Assets/Spine工具/atlas图片拆分-当前目录", false, 180)]
    static void AnalyzeImg1() {
        AnalyzeImg(false);
    }

    [MenuItem("Assets/Spine工具/atlas图片拆分-新目录X1", false, 180)]
    static void AnalyzeImg2() {
        AnalyzeImg(true);
    }

    [MenuItem("Assets/Spine工具/atlas图片拆分-新目录X2", false, 180)]
    static void AnalyzeImg222() {
        AnalyzeImg(true, 2);
    }

    static void AnalyzeImg(bool isGenToNewDir, float sizeRatio = 1) {
        CLogCat.GetInstance().Init(true, true);
        var dirArr = Selection.assetGUIDs;
        for (int i3 = 0; i3 < dirArr.Length; i3++) {
            var dir = AssetDatabase.GUIDToAssetPath(dirArr[i3]);
            if (Directory.Exists(dir) == false) {
                dir = Path.GetDirectoryName(dir);
                if (Directory.Exists(dir) == false) {
                    continue;
                }
            }
            var fileArr = Directory.GetFiles(dir, "*.atlas.txt", SearchOption.AllDirectories);
            for (int i5 = 0; i5 < fileArr.Length; i5++) {
                var atlasPath = fileArr[i5];
                if (atlasPath.EndsWith(".meta", StringComparison.Ordinal)) {
                    continue;
                }
                _AtlasSplit(atlasPath, isGenToNewDir, sizeRatio);
            }
        }

        AssetDatabase.Refresh();
    }

    static void _AtlasSplit(string atlasPath, bool isGenToNewDir, float sizeRatio = 1) {
        var index = atlasPath.LastIndexOf(".atlas.", StringComparison.Ordinal);
        if (index < 0) {
            index = atlasPath.LastIndexOf(".atlas", StringComparison.Ordinal);
            if (index < 0) { return; }
        }
        var textPath = atlasPath.Substring(0, index);
        var pngPath = textPath + ".png";
        if (File.Exists(pngPath) == false) {
            CLog.Ee(_tag, $"图片路径不存在.......{pngPath}");
            return;
        }

//        if (Directory.Exists(textPath)) {
//            CFile.DeleteDir(textPath);
//            CFile.DeleteFile(textPath + ".meta");
//        }
//        return;

        var dir0 = Path.GetDirectoryName(atlasPath);
        var assetAt = AssetDatabase.LoadAssetAtPath<TextAsset>(atlasPath);
        var tex0 = AssetDatabase.LoadAssetAtPath<Texture2D>(pngPath);
        // 创建序列化器
        var atlas = new Atlas2(assetAt.text, dir0);

        foreach (var rg in atlas.Regions) {
            Texture2D tex2 = null;
            if (rg.rotate) {
                tex2 = new Texture2D(rg.height, rg.width, TextureFormat.RGBA32, false);
                Batch2DUtils.CopyTexture(tex0, new RectInt(rg.x, tex0.height - rg.y - rg.width, rg.height, rg.width), tex2, 0, 0, true);
                tex2 = CTexture2D.RotateTexture90Clockwise(tex2, false);
            } else {
                tex2 = new Texture2D(rg.width, rg.height, TextureFormat.RGBA32, false);
                Batch2DUtils.CopyTexture(tex0, new RectInt(rg.x, tex0.height - rg.y - rg.height, rg.width, rg.height), tex2, 0, 0, true);
            }
            string savePath;
            if (isGenToNewDir) {
                savePath = $"{textPath}/{rg.name}.png";
            } else {
                savePath = $"{dir0}/{rg.name}.png";
            }
            if (sizeRatio.NoEqual(1)) {
                tex2 = CTexture2D.TextureScale(tex2, sizeRatio);
            }
            CTexture2D.SaveTexture(tex2, savePath);
        }

        Debug.Log(atlas.GetHashCode());
    }

    [MenuItem("Assets/Spine工具/Test修改", false, 180)]
    static void Start222() {
        CLogCat.GetInstance().Init(true, true);
        var dir = $"Assets/Art/C1172/PNG动画";
        //dir = $"Assets/Art/a01_out01";
        _Test_02();
        AssetDatabase.Refresh();
    }

    static void Start22(string dir) {
        //_DirReplace(".atlas.atlas", ".atlas.txt");
        //_DirReplace(".json.json", ".json");

        void _DirReplace(string findStr, string targetStr) {
            var fileArr = Directory.GetFiles(dir, $"*{findStr}", SearchOption.AllDirectories);
            for (int i5 = 0; i5 < fileArr.Length; i5++) {
                var atlasPath = fileArr[i5];
                var atlasPath2 = atlasPath.Replace(findStr, targetStr);
                AssetDatabase.MoveAsset(atlasPath, atlasPath2);
            }
        }

        Editor_U3dFile.SetTexInfo03(dir);
        AssetDatabase.Refresh();
    }

    static void _Test_02() {
        var soDir = $"/Users/xiahailong/Desktop/out01";
        var tgDir = $"Packages/com.xia9000.art09/C1172/PNG动画";
        var dir1 = Directory.GetDirectories(soDir, "*", SearchOption.TopDirectoryOnly);

        foreach (var soDir2 in dir1) {
            var name = soDir2.Substring(soDir.Length);
            var targetDir = tgDir + name;
            if (Directory.Exists(targetDir)) {
                CFile.DeleteDir(targetDir);
                CFile.DeleteFile(targetDir + ".meta");
            }
        }
    }
}

namespace Spine2 {
    public class Atlas2 : IEnumerable<AtlasRegion2> {
        readonly List<AtlasPage2> pages = new List<AtlasPage2>();
        List<AtlasRegion2> regions = new List<AtlasRegion2>();

        #region IEnumerable implementation
        public IEnumerator<AtlasRegion2> GetEnumerator() {
            return regions.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
            return regions.GetEnumerator();
        }
        #endregion

        public List<AtlasRegion2> Regions => regions;
        public List<AtlasPage2> Pages => pages;

        public Atlas2(string dataStr, string dir) {
            using (TextReader reader = new StringReader(dataStr)) {
                Load(reader, dir);
            }
        }

        public Atlas2(TextReader reader, string dir) {
            Load(reader, dir);
        }

        public Atlas2(List<AtlasPage2> pages, List<AtlasRegion2> regions) {
            this.pages = pages;
            this.regions = regions;
        }

        void Load(TextReader reader, string imagesDir) {
            string[] tuple = new string[4];
            AtlasPage2 page = null;
            while (true) {
                string line = reader.ReadLine();
                if (line == null)
                    break;
                if (line.Trim().Length == 0)
                    page = null;
                else if (page == null) {
                    page = new AtlasPage2();
                    page.name = line;

                    if (ReadTuple(reader, tuple) == 2) { // size is only optional for an atlas packed with an old TexturePacker.
                        page.width = int.Parse(tuple[0], CultureInfo.InvariantCulture);
                        page.height = int.Parse(tuple[1], CultureInfo.InvariantCulture);
                        ReadTuple(reader, tuple);
                    }
                    page.format = (Format)Enum.Parse(typeof(Format), tuple[0], false);

                    ReadTuple(reader, tuple);
                    page.minFilter = (TextureFilter)Enum.Parse(typeof(TextureFilter), tuple[0], false);
                    page.magFilter = (TextureFilter)Enum.Parse(typeof(TextureFilter), tuple[1], false);

                    string direction = ReadValue(reader);
                    page.uWrap = TextureWrap.ClampToEdge;
                    page.vWrap = TextureWrap.ClampToEdge;
                    if (direction == "x")
                        page.uWrap = TextureWrap.Repeat;
                    else if (direction == "y")
                        page.vWrap = TextureWrap.Repeat;
                    else if (direction == "xy")
                        page.uWrap = page.vWrap = TextureWrap.Repeat;

                    pages.Add(page);
                } else {
                    var region = new AtlasRegion2();
                    region.name = line;
                    region.page = page;

                    var rotateValue = ReadValue(reader);
                    if (rotateValue == "true")
                        region.degrees = 90;
                    else if (rotateValue == "false")
                        region.degrees = 0;
                    else
                        region.degrees = int.Parse(rotateValue);
                    region.rotate = region.degrees == 90;

                    ReadTuple(reader, tuple);
                    int x = int.Parse(tuple[0], CultureInfo.InvariantCulture);
                    int y = int.Parse(tuple[1], CultureInfo.InvariantCulture);

                    ReadTuple(reader, tuple);
                    int width = int.Parse(tuple[0], CultureInfo.InvariantCulture);
                    int height = int.Parse(tuple[1], CultureInfo.InvariantCulture);

                    region.u = x / (float)page.width;
                    region.v = y / (float)page.height;
                    if (region.rotate) {
                        region.u2 = (x + height) / (float)page.width;
                        region.v2 = (y + width) / (float)page.height;
                    } else {
                        region.u2 = (x + width) / (float)page.width;
                        region.v2 = (y + height) / (float)page.height;
                    }
                    region.x = x;
                    region.y = y;
                    region.width = Math.Abs(width);
                    region.height = Math.Abs(height);

                    if (ReadTuple(reader, tuple) == 4) { // split is optional
                        region.splits = new[] { int.Parse(tuple[0], CultureInfo.InvariantCulture), int.Parse(tuple[1], CultureInfo.InvariantCulture), int.Parse(tuple[2], CultureInfo.InvariantCulture), int.Parse(tuple[3], CultureInfo.InvariantCulture) };

                        if (ReadTuple(reader, tuple) == 4) { // pad is optional, but only present with splits
                            region.pads = new[] { int.Parse(tuple[0], CultureInfo.InvariantCulture), int.Parse(tuple[1], CultureInfo.InvariantCulture), int.Parse(tuple[2], CultureInfo.InvariantCulture), int.Parse(tuple[3], CultureInfo.InvariantCulture) };

                            ReadTuple(reader, tuple);
                        }
                    }

                    region.originalWidth = int.Parse(tuple[0], CultureInfo.InvariantCulture);
                    region.originalHeight = int.Parse(tuple[1], CultureInfo.InvariantCulture);

                    ReadTuple(reader, tuple);
                    region.offsetX = int.Parse(tuple[0], CultureInfo.InvariantCulture);
                    region.offsetY = int.Parse(tuple[1], CultureInfo.InvariantCulture);

                    region.index = int.Parse(ReadValue(reader), CultureInfo.InvariantCulture);

                    regions.Add(region);
                }
            }
        }

        static string ReadValue(TextReader reader) {
            string line = reader.ReadLine();
            int colon = line.IndexOf(':');
            if (colon == -1)
                throw new Exception("Invalid line: " + line);
            return line.Substring(colon + 1).Trim();
        }

        /// <summary>Returns the number of tuple values read (1, 2 or 4).</summary>
        static int ReadTuple(TextReader reader, string[] tuple) {
            string line = reader.ReadLine();
            int colon = line.IndexOf(':');
            if (colon == -1)
                throw new Exception("Invalid line: " + line);
            int i = 0, lastMatch = colon + 1;
            for (; i < 3; i++) {
                int comma = line.IndexOf(',', lastMatch);
                if (comma == -1)
                    break;
                tuple[i] = line.Substring(lastMatch, comma - lastMatch).Trim();
                lastMatch = comma + 1;
            }
            tuple[i] = line.Substring(lastMatch).Trim();
            return i + 1;
        }

        public void FlipV() {
            for (int i = 0, n = regions.Count; i < n; i++) {
                AtlasRegion2 region = regions[i];
                region.v = 1 - region.v;
                region.v2 = 1 - region.v2;
            }
        }

        /// <summary>Returns the first region found with the specified name. This method uses string comparison to find the region, so the result
        /// should be cached rather than calling this method multiple times.</summary>
        /// <returns>The region, or null.</returns>
        public AtlasRegion2 FindRegion(string name) {
            for (int i = 0, n = regions.Count; i < n; i++)
                if (regions[i].name == name)
                    return regions[i];
            return null;
        }
    }

    public enum Format {
        Alpha, Intensity, LuminanceAlpha, RGB565, RGBA4444,
        RGB888, RGBA8888
    }

    public enum TextureFilter {
        Nearest, Linear, MipMap, MipMapNearestNearest, MipMapLinearNearest,
        MipMapNearestLinear, MipMapLinearLinear
    }

    public enum TextureWrap { MirroredRepeat, ClampToEdge, Repeat }

    public class AtlasPage2 {
        public string name;
        public Format format;
        public TextureFilter minFilter;
        public TextureFilter magFilter;
        public TextureWrap uWrap;
        public TextureWrap vWrap;
        public object rendererObject;
        public int width, height;

        public AtlasPage2 Clone() {
            return MemberwiseClone() as AtlasPage2;
        }

        public override string ToString() => name;
    }

    public class AtlasRegion2 {
        public AtlasPage2 page;
        public string name;
        public int x, y, width, height;
        public float u, v, u2, v2;
        public float offsetX, offsetY;
        public int originalWidth, originalHeight;
        public int index;
        public bool rotate;
        public int degrees;
        public int[] splits;
        public int[] pads;

        public AtlasRegion2 Clone() {
            return MemberwiseClone() as AtlasRegion2;
        }

        public override string ToString() => name;
    }
}
#endif
